package genetica.cromosomas;

import genetica.cromosomas.evaluadores.EvaluadorFuncion;
import genetica.cromosomas.fenotipos.FenotipoFunciones;
import genetica.cromosomas.genes.Gen;
import genetica.cromosomas.genes.GenBool;

import java.util.ArrayList;
import java.util.Random;

public class CromosomaFuncion extends Cromosoma {

	protected Double valorFuncion;

	public Double getValorFuncion() {
		return valorFuncion;
	}

	public void setValorFuncion(Double valorFuncion) {
		this.valorFuncion = valorFuncion;
	}

	protected ArrayList<Double> xmin;
	protected ArrayList<Double> xmax;

	public CromosomaFuncion(ArrayList<Double> xmin, ArrayList<Double> xmax,
			double precision, Random r, EvaluadorFuncion evaluador) {
		super();
		int j = 0;
		int cont = 0;
		Integer tam = 0;
		this.xmax = xmax;
		this.xmin = xmin;

		for (int i = 0; i < xmax.size(); i++) {
			tam = Double.valueOf(
					Math.log10(1 + (xmax.get(i) - xmin.get(i)) / precision)
							/ Math.log10(2)).intValue();
			Cromosoma.longGenes.add(tam);
			for (j = cont; j < cont + tam; j++)
				// se añade siempre en la posicion cont (esperemos)
				genes.add(new GenBool(r.nextBoolean()));
			cont = j;
		}

		// NO NECESITAMOS CALCULAR FENOTIPO Y EVALUAR YA QUE SE HACE AL EVALUAR
		// POBLACION
		Cromosoma.evaluador = evaluador;

	}

	// TODO terminar
	@SuppressWarnings("unchecked")
	public CromosomaFuncion(CromosomaFuncion c) {
		super();
		// TODO poner xmin xmax
		// TODO duplicar bien el fenotipo en un futuro
		this.genes = (ArrayList<Gen>) c.genes.clone();
		// NOTA PARA M: NO hace falta dublicar porque no se van a cambiar
		this.xmax = c.xmax;
		// this.longGenes = c.longGenes; No es necesario porque es estatico
		this.xmin = c.xmin;
		this.aptitud = c.aptitud;
		// no es necesario porque es estatico
		// this.evaluador = c.evaluador;
	}

	@Override
	public void calcularFenotipo() {
		int posIni = 0;
		for (int i = 0; i < this.xmax.size(); i++) {
			this.fenotipo.add(new FenotipoFunciones(Double.valueOf(xmin.get(i)
					+ GenBool.binToDec(genes.subList(posIni,
							posIni + longGenes.get(i)))
					* ((xmax.get(i) - xmin.get(i)) / (Math.pow(2,
							longGenes.get(i)) - 1)))));
			posIni += longGenes.get(i);
		}

	}

	@Override
	public String toString() {
		String cadena = "";
		cadena += "Fenotipo: ";
		for (int i = 0; i < fenotipo.size(); i++) {
			cadena += "var_" + i + "=" + fenotipo.get(i) + "|";
		}
		cadena += "valor de la funcion="
				+ ((EvaluadorFuncion) evaluador)
						.getFunctionValue(fenotipo) + "|Aptitud="
				+ this.aptitud;
		return cadena;
	}

	public CromosomaFuncion clone() {
		return new CromosomaFuncion(this);
	}
	@Override
	public void codifica(){
		throw new Error("no soportado");
	}
	@Override
	public void decodifica(){
		throw new Error("no soportado");
	}

}
